import time
from collections import OrderedDict
from threading import Lock
from typing import Optional, Dict, Any

# 从utils模块导入MySQL查询函数
from utils import query_mysql

class MediaCache:
    def __init__(self, capacity: int = 1000):  
        self.cache = OrderedDict()  # key: fid, value: 文件信息对象
        self.capacity = capacity
        self.lock = Lock()  # 线程锁，确保线程安全
        
    def get(self, fid: str) -> Optional[Dict[str, Any]]:       
        with self.lock:
            if fid in self.cache:
                # 更新访问时间
                self.cache[fid]['last_access'] = int(time.time())
                # 移动到最近使用的位置
                self.cache.move_to_end(fid)
                # 返回对象的副本，避免外部修改缓存内容
                return dict(self.cache[fid])
            return None
    
    def _add_to_cache(self, fid: str, file_info: Dict[str, Any]):
        with self.lock:
            # 确保包含last_access字段
            file_info['last_access'] = int(time.time())
            
            # 如果缓存已满，删除最早使用的项
            if len(self.cache) >= self.capacity and fid not in self.cache:
                self.cache.popitem(last=False)
                
            # 直接存储文件信息对象
            self.cache[fid] = file_info
            self.cache.move_to_end(fid)
    
    def _load_from_mysql(self, fid: str, corpid: str) -> Optional[Dict[str, Any]]:       
        try:
            if not corpid:
                print("错误: 未提供corpid参数")
                return None
            
            table_name = f"file_info_{corpid}"
            try:
                # 查询文件信息的主要字段，metadesc保持原始字符串形式
                sql_query = f"SELECT fid, delflag, fpath, metadesc, mimeid, name, fsize, mtime, ftype,vpath " \
                          f"FROM {table_name} WHERE fid = %s"
                
                result = query_mysql(sql_query, params=(fid,), fetchone=True)
                if result:
                    # 构建结果字典
                    file_info = {
                        'fid': result[0],
                        'delflag': result[1],
                        'fpath': result[2],
                        'metadesc': result[3],  # 保持原始字符串形式，不解析
                        'mimeid': result[4],
                        'name': result[5] if len(result) > 5 else '',
                        'fsize': result[6] if len(result) > 6 else 0,
                        'mtime': result[7] if len(result) > 7 else 0,
                        'ftype': result[8] if len(result) > 8 else 0,
                        'vpath': result[9] if len(result) > 9 else '',
                    }
                    
                    return file_info
            except Exception as e:
                print(f"查询表 {table_name} 失败: {e}")
                return None
        except Exception as e:
            print(f"从MySQL加载文件信息失败: {e}")
            return None
       
    def remove(self, fid: str):       
        with self.lock:
            if fid in self.cache:
                del self.cache[fid]
    
    def get_fid_mysql(self, fid: str, corpid: str) -> Optional[Dict[str, Any]]:      
        # 先尝试从缓存获取
        cached_info = self.get(fid)
        if cached_info:
            return cached_info
        
        # 从MySQL加载
        file_info = self._load_from_mysql(fid, corpid)
        if file_info:
            # 添加到缓存
            self._add_to_cache(fid, file_info)
            # 返回副本
            return dict(file_info)
        return file_info


# 创建全局缓存实例
media_cache = MediaCache(capacity=1000)

# 辅助函数，用于在应用中方便地访问缓存
def get_fid_cache(fid: str, corpid: str = None) -> Optional[Dict[str, Any]]:   
    # 为保持兼容性，忽略corpid参数
    return media_cache.get(fid)

# 辅助函数，强制从MySQL获取文件信息并更新缓存
def get_fid_from_mysql(fid: str, corpid: str) -> Optional[Dict[str, Any]]:   
    return media_cache.get_fid_mysql(fid, corpid)

# 辅助函数，用于处理metadesc字符串，转换为JSON格式的元数据
# 此函数保留供HTTP请求处理时使用
def meta_buffer_json(metainfo: str) -> Dict[str, Any]:
    """
    将分号分隔的元数据字符串转换为字典
    :param metainfo: 分号分隔的元数据字符串
    :return: 包含元数据的字典
    """
    result = {}
    if not metainfo:
        return result
    
    # 按分号分割字符串
    parts = metainfo.split(';')
    if not parts:
        return result
    
    # 根据文件类型处理不同的元数据字段
    if len(parts) > 1:
        if len(parts) >= 1 and parts[0].strip():
            try:
                ftype = int(parts[0].strip())
                # 根据文件类型处理
                if ftype == 2:  # 图片
                    if len(parts) > 1:
                        result['resolvepower'] = parts[1].strip()
                elif ftype == 7:  # 视频
                    if len(parts) > 1:
                        result['codetime'] = parts[1].strip()
                    if len(parts) > 2:
                        result['vcode'] = parts[2].strip()
                    if len(parts) > 3:
                        result['profile'] = parts[3].strip()
                    if len(parts) > 4:
                        result['resolvepower'] = parts[4].strip()
                    if len(parts) > 5:
                        result['vbit_rate'] = parts[5].strip()
                    if len(parts) > 6:
                        result['display_ratio'] = parts[6].strip()
                    if len(parts) > 7:
                        result['bittype'] = parts[7].strip()
                    if len(parts) > 8:
                        result['pix_fmt'] = parts[8].strip()
                    if len(parts) > 9:
                        result['b_frames'] = parts[9].strip()
                    if len(parts) > 10:
                        result['frame_rate'] = parts[10].strip()
                    if len(parts) > 11:
                        result['level'] = parts[11].strip()
                    if len(parts) > 12:
                        result['acode'] = parts[12].strip()
                    if len(parts) > 13:
                        result['sample_rate'] = parts[13].strip()
                    if len(parts) > 14:
                        result['abit_rate'] = parts[14].strip()
                    if len(parts) > 15:
                        result['channel'] = parts[15].strip()
                elif ftype == 4:  # 音频
                    if len(parts) > 1:
                        result['acode'] = parts[1].strip()
                    if len(parts) > 2:
                        result['sample_rate'] = parts[2].strip()
                    if len(parts) > 3:
                        result['abit_rate'] = parts[3].strip()
                    if len(parts) > 4:
                        result['channel'] = parts[4].strip()
                    if len(parts) > 5:
                        result['codetime'] = parts[5].strip()
            except ValueError:
                pass
    
    return result

# 辅助函数，获取文件详细信息
def get_fileinfo(corpid: str, fid: str) -> Optional[Dict[str, Any]]:
    """
    获取文件详细信息
    :param corpid: 企业ID
    :param fid: 文件ID
    :return: 包含文件详细信息的字典
    """
    # 直接从MySQL获取文件信息（会自动缓存）
    return get_fid_from_mysql(fid, corpid)

